<template>
  <div>
    <h3>Base64 单一文件上传</h3>
    <div class="upload_div">
      <input
        ref="fileInput"
        type="file"
        class="upload_input"
        @change="changeFile"
      />
      <div class="upload_button_box">
        <button
          class="upload_button select"
          @click="chooseFile"
          :class="[{ disabled: disabledStyle }]"
        >
          选择文件
        </button>
      </div>
      <div class="upload_tip" v-if="uploadTipVisible">
        只能上传PNG/JPG/JPEG格式的图片，且大小不能超过10MB
      </div>
      <ul
        class="upload_list"
        v-if="uploadListVisible"
        @click="removeSelectedFile"
      >
        <span v-for="file in files" :key="file.name">
          文件：{{ file.name }}
          <el-button type="text" size="small">移除</el-button>
        </span>
      </ul>
    </div>
  </div>
</template>

<script>
import { uploadBase64SingleFile } from "@/api/upload/Base64SingleUploader.js";

export default {
  mounted() {},
  data() {
    return {
      uploadTipVisible: true,
      uploadListVisible: false,
      files: [],
      disabledStyle: false,
      loadingStyle: false,
    };
  },
  props: ["onBeforeUpload"],
  methods: {
    chooseFile() {
      this.$refs.fileInput.click();
    },
    encodeImageFileToBase64(file) {
      return new Promise((resolve) => {
        let fileReader = new FileReader();
        fileReader.readAsDataURL(file);
        fileReader.onload = (event) => {
          resolve(event.target.result);
        };
      });
    },
    async changeFile(event) {
      this.files.length = 0;

      const file = event.srcElement.files[0];

      if (!file) return;

      const base64 = await this.encodeImageFileToBase64(file);

      this.files.push({
        name: file.name,
        type: file.type,
        base64: base64,
      });

      this.showFileList();

      this.uploadFile();
    },
    async uploadFile() {
      // 如果没有选择文件，则提示先选择文件
      if (this.files.length == 0) {
        this.$message({
          type: "info",
          message: "请先选择文件",
        });
        return;
      }

      // 如果已经选择文件，则判断文件是否符合要求
      const file = this.files[0];
      let shouldUpload = true;
      if (this.onBeforeUpload) {
        shouldUpload = this.onBeforeUpload(file);
      }

      if (!shouldUpload) {
        this.$message({
          type: "warning",
          message: "文件不符合要求",
        });
        return;
      }

      // 如果文件符合要求，则将文件名和文件的base64编码上传到服务器
      this.setButtonEnableStatus(false);
      try {
        const dotIndex = file.base64.indexOf(",");
        const base64 = file.base64.substring(dotIndex + 1);
        const resultVo = await uploadBase64SingleFile({
          base64: base64,
          name: file.name,
          type: file.type,
        });
        if (resultVo.code == 200) {
          this.$message({
            type: "success",
            message: "上传文件成功：" + resultVo.data,
          });
          return;
        }
        throw resultVo.msg;
      } catch (err) {
        this.$message({
          type: "error",
          message: "上传文件失败" + err,
        });
      } finally {
        this.clearFileList();
        this.setButtonEnableStatus(true);
      }
    },
    showFileList() {
      this.uploadTipVisible = false;
      this.uploadListVisible = true;
    },
    hideFileList() {
      this.uploadTipVisible = true;
      this.uploadListVisible = false;
    },
    removeSelectedFile(event) {
      const target = event.target;
      if (target.tagName === "SPAN") {
        // 点击的是移除按钮
        this.uploadTipVisible = true;
        this.uploadListVisible = false;
        this.files.length = 0;
      }
    },
    clearFileList() {
      this.hideFileList();
      this.files.length = 0;
      this.$refs.fileInput.value = null;
    },
    setButtonEnableStatus(status) {
      this.disabledStyle = !status;
      this.loadingStyle = !status;
    },
  },
};
</script>

<style scoped>
.upload_div {
  margin: auto;
  width: 400px;
  height: 150px;
  border: #ccc dashed 1px;
}
.upload_input {
  display: none;
}
.upload_button_box button {
  margin: 5px;
}
.upload_button {
  size: 16px;
  padding: 5px;
  border-radius: 5px;
  border: #ccc solid 1px;
}
.upload_button:active {
  size: 16px;
  border-radius: 5px;
  border: #ccc outset 1px;
}
.select {
  background-color: #66cef6;
}
.upload {
  background-color: #cafe4f;
}
.upload::after {
  content: "上传到服务器";
}
.upload_tip {
  font-size: 12px;
}
.upload_list {
  font-size: 12px;
}

.disabled {
  pointer-events: none;
  background-color: #ccc;
}

.loading {
  width: 23px;
  height: 23px;
  border: 5px solid #ccc;
  border-bottom-color: #ff3d00;
  border-radius: 50%;
  display: inline-block;
  background: #fff;
  animation: rotation 0.7s linear infinite;
  pointer-events: none;
}
.loading::after {
  content: "";
}

@keyframes rotation {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
</style>